package com.entmanage.base.oa.service.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.entmanage.base.oa.domain.OaLeaveApply;
import com.entmanage.common.core.domain.entity.SysUser;
import com.entmanage.common.utils.DateUtils;
import com.entmanage.common.utils.StringUtils;
import com.entmanage.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.entmanage.common.utils.SecurityUtils;
import com.entmanage.base.oa.mapper.OaReissueApplyMapper;
import com.entmanage.base.oa.domain.OaReissueApply;
import com.entmanage.base.oa.service.IOaReissueApplyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 补卡申请Service业务层处理
 *
 * @author lsq
 * @date 2025-09-19
 */
@Service
public class OaReissueApplyServiceImpl implements IOaReissueApplyService
{
    private static final Logger log = LoggerFactory.getLogger(OaLeaveApplyServiceImpl.class);

    @Autowired
    private OaReissueApplyMapper oaReissueApplyMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private ISysUserService sysUserService;

    /**
     * 查询补卡申请
     *
     * @param applyId 补卡申请主键
     * @return 补卡申请
     */
    @Override
    public OaReissueApply selectOaReissueApplyByApplyId(Long applyId)
    {
        return oaReissueApplyMapper.selectOaReissueApplyByApplyId(applyId);
    }

    /**
     * 查询补卡申请列表
     *
     * @param oaReissueApply 补卡申请
     * @return 补卡申请
     */
    @Override
    public List<OaReissueApply> selectOaReissueApplyList(OaReissueApply oaReissueApply)
    {
        return oaReissueApplyMapper.selectOaReissueApplyList(oaReissueApply);
    }

    /**
     * 新增补卡申请
     *
     * @param oaReissueApply 补卡申请
     * @return 结果
     */
    @Override
    public int insertOaReissueApply(OaReissueApply oaReissueApply)
    {
        // 保存用户和部门id
        oaReissueApply.setUserId(SecurityUtils.getUserId());
        oaReissueApply.setDeptId(SecurityUtils.getDeptId());
        oaReissueApply.setCreateTime(DateUtils.getNowDate());
    oaReissueApply.setCreateBy(SecurityUtils.getUsername());
        return oaReissueApplyMapper.insertOaReissueApply(oaReissueApply);
    }

    /**
     * 修改补卡申请
     *
     * @param oaReissueApply 补卡申请
     * @return 结果
     */
    @Override
    public int updateOaReissueApply(OaReissueApply oaReissueApply)
    {
        oaReissueApply.setUpdateTime(DateUtils.getNowDate());
    oaReissueApply.setUpdateBy(SecurityUtils.getUsername());
        return oaReissueApplyMapper.updateOaReissueApply(oaReissueApply);
    }

    /**
     * 批量删除补卡申请
     *
     * @param applyIds 需要删除的补卡申请主键
     * @return 结果
     */
    @Override
    public int deleteOaReissueApplyByApplyIds(Long[] applyIds)
    {
        return oaReissueApplyMapper.deleteOaReissueApplyByApplyIds(applyIds);
    }

    /**
     * 删除补卡申请信息
     *
     * @param applyId 补卡申请主键
     * @return 结果
     */
    @Override
    public int deleteOaReissueApplyByApplyId(Long applyId)
    {
        return oaReissueApplyMapper.deleteOaReissueApplyByApplyId(applyId);
    }

    /**
     * 发送补卡申请审批通知邮件（异步）
     *
     * @param approverIds      审批人用户ID列表
     * @param ccIds            抄送人用户ID列表
     * @param reissueTimes     补卡时间（如：2025-09-19 09:15）
     * @param reissueReasons   补卡事由
     * @param applicantName    申请人姓名
     */
    @Override
    @Async
    public void sendReissueApprovalEmail(
            List<Long> approverIds,
            List<Long> ccIds,
            String reissueTimes,
            String reissueReasons,
            String applicantName) {

        log.info("【开始发送补卡申请审批邮件】补卡时间={}，审核人IDs={}, 抄送IDs={}",
                reissueTimes,
                approverIds != null ? approverIds : "无",
                ccIds != null ? ccIds : "无");

        // 参数基本校验
        if (StringUtils.isEmpty(reissueTimes)) {
            log.warn("邮件发送中止：补卡时间为空");
            return;
        }
        if (StringUtils.isEmpty(reissueReasons)) {
            log.warn("邮件发送中止：补卡事由为空");
            return;
        }

        Set<String> toEmails = new HashSet<>();
        Set<String> ccEmails = new HashSet<>();

        // 查询审批人邮箱
        if (approverIds != null && !approverIds.isEmpty()) {
            List<SysUser> approvers = sysUserService.selectUserByIds(approverIds);
            toEmails.addAll(filterValidEmails(approvers, "审批人"));
        }

        // 查询抄送人邮箱
        if (ccIds != null && !ccIds.isEmpty()) {
            List<SysUser> ccs = sysUserService.selectUserByIds(ccIds);
            ccEmails.addAll(filterValidEmails(ccs, "抄送人"));
        }

        if (toEmails.isEmpty() && ccEmails.isEmpty()) {
            log.warn("未找到任何有效邮箱地址，终止发送");
            return;
        }

        // 构建邮件主题和内容
        String subject = "[补卡申请] " + applicantName + " 提交了补卡申请";
        String content = String.format(
                "您好：\n\n" +
                        "%s 提交了一条补卡申请。\n" +
                        "补卡时间：%s\n" +
                        "补卡事由：%s\n\n" +
                        "请登录OA系统进行审批。\n\n" +
                        "—— OA系统自动通知",
                applicantName != null ? applicantName : "某员工",
                reissueTimes,
                reissueReasons
        );

        try {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom("1911708828@qq.com"); // 修改为你的发件邮箱
            message.setSubject(subject);
            message.setText(content);

            // 发送给审批人（To）
            if (!toEmails.isEmpty()) {
                message.setTo(toEmails.toArray(new String[0]));
                javaMailSender.send(message);
                toEmails.forEach(email -> log.info("补卡申请邮件已发送至审批人: {}", email));
            }

            // 单独发送抄送（Cc）—— SimpleMailMessage 不支持混合 To + Cc，所以单独发
            if (!ccEmails.isEmpty()) {
                SimpleMailMessage ccMessage = new SimpleMailMessage(message);
                ccMessage.setTo(ccEmails.toArray(new String[0]));
                javaMailSender.send(ccMessage);
                ccEmails.forEach(email -> log.info("补卡申请邮件已抄送至: {}", email));
            }

            log.info("【补卡申请邮件发送完成】共发送 {} 封邮件", toEmails.size() + ccEmails.size());

        } catch (Exception e) {
            log.error("发送补卡申请邮件时发生异常", e);
        }
    }

    /**
     * 从员工列表中提取非空邮箱，并记录日志
     */
    private Set<String> filterValidEmails(List<SysUser> users, String role) {
        return users.stream()
                .filter(user -> user != null && StringUtils.isNotEmpty(user.getEmail()))
                .map(SysUser::getEmail)
                .collect(Collectors.toSet());
    }

    @Override
    public List<OaReissueApply> selectByApproverId(Long approverId) {
        return oaReissueApplyMapper.selectByApproverId(approverId);
    }

    @Override
    public List<OaReissueApply> selectByCcId(Long currentUserId) {
        return oaReissueApplyMapper.selectByCcId(currentUserId);
    }
}
